﻿using System.Collections.Generic;
using System.Threading;

namespace YanZhiwei.DotNet3._5.Utilities.Common
{
    /// <summary>
    /// 同步缓存类
    /// </summary>
    /// <typeparam name="TKey"></typeparam>
    /// <typeparam name="TValue"></typeparam>
    public class SynchronizedDictionary<TKey, TValue>
    {
        #region AddOrUpdateStatus enum

        public enum AddOrUpdateStatus
        {
            Added,
            Updated,
            Unchanged
        } ;

        #endregion

        #region 属性
        protected ReaderWriterLockSlim _lock = new ReaderWriterLockSlim();
        protected Dictionary<TKey, TValue> _dictionary = new Dictionary<TKey, TValue>();
        #endregion

        #region 取值
        /// <summary>
        /// 取值
        /// </summary>
        /// <param name="key">键</param>
        /// <returns></returns>
        public TValue Get(TKey key)
        {
            TValue result = default(TValue);
            _lock.EnterReadLock();
            try
            {
                if (_dictionary.ContainsKey(key))
                {
                    result = _dictionary[key];
                }
            }
            finally
            {
                _lock.ExitReadLock();
            }

            return result;
        }
        #endregion

        #region 获取全部Values
        /// <summary>
        /// 获取全部Values
        /// </summary>
        /// <returns></returns>
        public ICollection<TValue> GetAll()
        {
            ICollection<TValue> result;
            _lock.EnterReadLock();
            try
            {
                result = _dictionary.Values;
            }
            finally
            {
                _lock.ExitReadLock();
            }

            return result;
        }
        #endregion

        #region 获取包含在 Dictionary 中的键/值对的数目
        /// <summary>
        /// 获取包含在 Dictionary 中的键/值对的数目
        /// </summary>
        public int Count
        {
            get { return _dictionary.Count; }
        }
        #endregion

        #region 确定 Dictionary 是否包含指定的键
        /// <summary>
        /// 确定 Dictionary 是否包含指定的键
        /// </summary>
        /// <param name="key">键</param>
        /// <returns></returns>
        public bool Contains(TKey key)
        {
            bool result = false;
            _lock.EnterReadLock();
            try
            {
                result = _dictionary.ContainsKey(key);
            }
            finally
            {
                _lock.ExitReadLock();
            }

            return result;
        }
        #endregion

        #region 获取与指定的键相关联的值。
        /// <summary>
        /// 获取与指定的键相关联的值
        /// </summary>
        /// <param name="key">键</param>
        /// <param name="value">值</param>
        /// <returns></returns>
        public bool TryGetValue(TKey key, out TValue value)
        {
            bool result = false;
            _lock.EnterReadLock();
            try
            {
                result = _dictionary.TryGetValue(key, out value);
            }
            finally
            {
                _lock.ExitReadLock();
            }

            return result;
        }
        #endregion

        #region 将指定的键和值添加到字典中
        /// <summary>
        /// 将指定的键和值添加到字典中
        /// </summary>
        /// <param name="key">键</param>
        /// <param name="value">值</param>
        /// <returns></returns>
        public bool Add(TKey key, TValue value)
        {
            bool result = false;
            _lock.EnterWriteLock();
            try
            {
                if (!_dictionary.ContainsKey(key))
                {
                    _dictionary.Add(key, value);
                    result = true;
                }
            }
            finally
            {
                _lock.ExitWriteLock();
            }

            return result;
        }
        #endregion

        #region 将指定的键和值添加到字典中,超过设置的超时时间将放弃
        /// <summary>
        /// 将指定的键和值添加到字典中,超过设置的超时时间将放弃
        /// </summary>
        /// <param name="key">键</param>
        /// <param name="value">值</param>
        /// <param name="timeout">超时时间</param>
        /// <returns></returns>
        public bool AddWithTimeout(TKey key, TValue value, int timeout)
        {
            bool result = false;
            if (_lock.TryEnterWriteLock(timeout))
            {
                try
                {
                    if (!_dictionary.ContainsKey(key))
                    {
                        _dictionary.Add(key, value);
                        result = true;
                    }
                }
                finally
                {
                    _lock.ExitWriteLock();
                }
            }

            return result;
        }
        #endregion

        #region  将指定的键和值添加到字典中,如果存在就更新，不存在就添加
        /// <summary>
        /// 将指定的键和值添加到字典中,如果存在就更新，不存在就添加
        /// </summary>
        /// <param name="key">键</param>
        /// <param name="value">值</param>
        /// <returns></returns>
        public AddOrUpdateStatus AddOrUpdate(TKey key, TValue value)
        {
            _lock.EnterUpgradeableReadLock();
            try
            {
                TValue result;
                if (_dictionary.TryGetValue(key, out result))
                {
                    if (Equals(result, value))
                    {
                        return AddOrUpdateStatus.Unchanged;
                    }
                    else
                    {
                        _lock.EnterWriteLock();
                        try
                        {
                            _dictionary[key] = value;
                        }
                        finally
                        {
                            _lock.ExitWriteLock();
                        }
                        return AddOrUpdateStatus.Updated;
                    }
                }
                else
                {
                    _lock.EnterWriteLock();
                    try
                    {
                        _dictionary.Add(key, value);
                    }
                    finally
                    {
                        _lock.ExitWriteLock();
                    }
                    return AddOrUpdateStatus.Added;
                }
            }
            finally
            {
                _lock.ExitUpgradeableReadLock();
            }
        }
        #endregion

        #region 从 Dictionary 中移除所指定的键的值
        /// <summary>
        /// 从 Dictionary 中移除所指定的键的值
        /// </summary>
        /// <param name="key">键</param>
        /// <returns></returns>
        public bool Remove(TKey key)
        {
            bool result = false;
            _lock.EnterWriteLock();
            try
            {
                if (_dictionary.ContainsKey(key))
                {
                    _dictionary.Remove(key);
                    result = true;
                }
            }
            finally
            {
                _lock.ExitWriteLock();
            }
            return result;
        }
        #endregion

        #region 从 Dictionary 中移除所有的键和值
        /// <summary>
        /// 从 Dictionary 中移除所有的键和值
        /// </summary>
        public void Clear()
        {
            _lock.EnterWriteLock();
            try
            {
                _dictionary.Clear();
            }
            finally
            {
                _lock.ExitWriteLock();
            }
        }
        #endregion

        #region 索引器
        public TValue this[TKey key]
        {
            get
            {
                TValue result;
                _lock.EnterReadLock();
                try
                {
                    result = _dictionary[key];
                }
                finally
                {
                    _lock.ExitReadLock();
                }
                return result;
            }
            set
            {
                _lock.EnterWriteLock();
                try
                {
                    _dictionary[key] = value;
                }
                finally
                {
                    _lock.ExitWriteLock();
                }
            }
        }
        #endregion

        #region 获取包含 Dictionary 中的键的集合
        /// <summary>
        /// 获取包含 Dictionary 中的键的集合
        /// </summary>
        public Dictionary<TKey, TValue>.KeyCollection Keys
        {
            get
            {
                Dictionary<TKey, TValue>.KeyCollection result;
                _lock.EnterReadLock();
                try
                {
                    result = _dictionary.Keys;
                }
                finally
                {
                    _lock.ExitReadLock();
                }

                return result;
            }
        }
        #endregion

        #region 获取包含 Dictionary 中的值的集合
        /// <summary>
        /// 获取包含 Dictionary 中的值的集合
        /// </summary>
        public Dictionary<TKey, TValue>.ValueCollection Values
        {
            get
            {
                Dictionary<TKey, TValue>.ValueCollection result;
                _lock.EnterReadLock();
                try
                {
                    result = _dictionary.Values;
                }
                finally
                {
                    _lock.ExitReadLock();
                }
                return result;
            }
        }
        #endregion
    }
}
